﻿using System;
using System.Collections.Generic;
using System.Text;

namespace VsTortoiseSVN
{
    /// <summary>
    /// TortoiseProc is a helper class to ease execution of TortoiseSVN commands.
    /// </summary>
    public static class TortoiseProc
    {
        private static class Revision
        {
            public const int Head = -1;
            public const int Base = -2;
            public const int WorkingCopy = -3;
        }

        /// <summary>
        /// Execute TortoiseSVN with the given arguments string.
        /// </summary>
        private static void Exec(string arguments)
        {
            string fileName = "TortoiseProc.exe";

            Output.Instance.WriteLine(string.Format("{0} {1}", fileName, arguments));
            Win32.ShellExecute(fileName, arguments);
        }
        
        public static void Properties(string path)
        {
            string args = "/command:properties" + BuildPathParam(path);
            Exec(args);
        }

        public static void Properties(ICollection<string> pathes)
        {
            string args = "/command:properties" + BuildPathParam(pathes);
            Exec(args);
        }

        public static void Add(string path)
        {
            string args = "/command:add" + BuildPathParam(path);
            Exec(args);
        }

        public static void Add(ICollection<string> pathes)
        {
            string args = "/command:add" + BuildPathParam(pathes);
            Exec(args);
        }

        public static void Commit(string path)
        {
            string args = "/command:commit" + BuildPathParam(path);
            Exec(args);
        }

        public static void Commit(ICollection<string> pathes)
        {
            string args = "/command:commit" + BuildPathParam(pathes);
            Exec(args);
        }
        
        public static void Diff(string path)
        {
            string args = "/command:diff" + BuildPathParam(path);
            Exec(args);
        }
        
        public static void Diff(string path, int line)
        {
            string args = string.Format("/command:diff /line:{0} {1}", line, BuildPathParam(path));
            Exec(args);
        }
        
        public static void Diff(ICollection<string> pathes)
        {
            string args = "/command:diff" + BuildPathParam(pathes);
            Exec(args);
        }
        
        public static void DiffWithPreviousVersion(string path)
        {
            SharpSvn.SvnStatusEventArgs status;
            if (SvnHelper.FileStatus(path, out status))
            {
                long startrev = status.WorkingCopyInfo.LastChangeRevision - 1;
                if (startrev > 0)
                {
                    string args = string.Format("/command:diff {0} /startrev:{1} /endrev:{2}", BuildPathParam(path), Revision.WorkingCopy, startrev);
                    Exec(args);
                }
            }
        }

        public static void DiffWithPreviousVersion(string path, int line)
        {
            SharpSvn.SvnStatusEventArgs status;
            if (SvnHelper.FileStatus(path, out status))
            {
                long startrev = status.WorkingCopyInfo.LastChangeRevision - 1;
                if (startrev > 0)
                {
                    string args = string.Format("/command:diff /line:{0} {1} /startrev:{2} /endrev:{3}", line, BuildPathParam(path), Revision.WorkingCopy, startrev);
                    Exec(args);
                }
            }
        }

        public static void CompareWithBase(ICollection<string> pathes)
        {
            foreach (string path in pathes)
            {
                // http://tortoisesvn.tigris.org/ds/viewMessage.do?dsForumId=4061&dsMessageId=2448492
                string args = string.Format("/command:diff {0}", BuildPathParam(path));
                Exec(args);
            }
        }

        public static void Blame(string path)
        {
            string args = "/command:blame" + BuildPathParam(path);
            Exec(args);
        }

        public static void Blame(string path, int line)
        {
            string args = string.Format("/command:blame /line:{0} {1}", line, BuildPathParam(path));
            Exec(args);
        }

        public static void EditConflicts(string path)
        {
            string args = "/command:conflicteditor" + BuildPathParam(path);
            Exec(args);
        }

        public static void Resolve(string path)
        {
            string args = "/command:resolve" + BuildPathParam(path);
            Exec(args);
        }

        public static void Resolve(ICollection<string> pathes)
        {
            string args = "/command:resolve" + BuildPathParam(pathes);
            Exec(args);
        }

        public static void Revert(string path)
        {
            string args = "/command:revert" + BuildPathParam(path);
            Exec(args);
        }

        public static void Revert(ICollection<string> pathes)
        {
            string args = "/command:revert" + BuildPathParam(pathes);
            Exec(args);
        }

        public static void ShowLog(string path)
        {
            string args = "/command:log" + BuildPathParam(path);
            Exec(args);
        }

        public static void Update(string path)
        {
            string args = "/command:update" + BuildPathParam(path);
            Exec(args);
        }

        public static void Update(ICollection<string> pathes)
        {
            string args = "/command:update" + BuildPathParam(pathes);
            Exec(args);
        }

        private static string BuildPathParam(string path)
        {
            return " /path:\"" + path + "\"";
        }

        /// <summary>
        /// Builds the "path" parameter.
        /// TortoiseSVN expects pathes delimited by a star symbol.
        /// Example:
        /// /path:"c:\folder\file.bin*c:\another folder\file.txt"
        /// </summary>
        private static string BuildPathParam(ICollection<string> pathes)
        {
            List<string> mergedPathes = new List<string>(64);

            // Remove sub-directories
            PathHelper.RemoveSubDirectories(mergedPathes, pathes);

            // Build the TortoiseSVN Update string
            string pathList = string.Empty;
            for (int n = 0; n < mergedPathes.Count; ++n)
            {
                if (string.IsNullOrEmpty(pathList))
                    pathList += mergedPathes[n];
                else
                    pathList += "*" + mergedPathes[n];
            }

            return " /path:\"" + pathList + "\"";
        }
    }
}
